#ifndef QLIB_HEADER_ELLIPSE
#define QLIB_HEADER_ELLIPSE

#include "qlib/core/object.h"
#include "qlib/core/vec2.h"
#include "qlib/geo/polygon.h"
#include "qlib/layout/repetition.h"
#include "qlib/layout/property.h"

namespace qlib {
enum struct GeoPartType;

class Ellipse;
using EllipsePtrArray = std::vector<std::shared_ptr<Ellipse>>;
// 0: 中心， 1: 顶点， 2: 边， 3: 边中点，4: box顶点, 5: box边, 6: box边中心
using EllipseParts = std::tuple<Vec2d, Vec2dArray, std::vector<Vec2dArray>, Vec2dArray, Vec2dArray, std::vector<Vec2dArray>, Vec2dArray>;

class QLIB_API Ellipse {
 public:
  Ellipse();
  Ellipse(Vec2d _center, Vec2d _radius, float _rotation, double _tolerance = 1e-3, uint32_t _layer = 0, uint32_t _datatype = 0);

  Ellipse(const Ellipse& oth);
  Ellipse& operator=(const Ellipse& other);

  using s_ptr = std::shared_ptr<Ellipse>;
  template <typename... Args>
  static s_ptr create(Args... args) {
    return std::make_shared<Ellipse>(args...);
  }
  // template <>
  static s_ptr create() {
    return std::make_shared<Ellipse>();
  }
  static s_ptr create(const Ellipse& value) { return std::make_shared<Ellipse>(value); }

  s_ptr copy() const;
  void init(Vec2d _center, Vec2d _radius, float _rotation, double _tolerance = 1e-3, uint32_t _layer = 0, uint32_t _datatype = 0);

  double area() const;

  // 从x正半轴0度逆时针生成点
  Polygon::s_ptr to_polygon(bool is_tri = false);
  Vec2dArray bounding_box_points() { return box_to_points(bounding_box()); };
  Vec2dArray bounding_box();

  // 定向包围盒
  Vec2dArray obb();

  void scale(double sx, double sy);
  void mirror(Vec2d p0, Vec2d p1);
  void rotate(double angle, Vec2d center);
  void translate(double dx, double dy);
  void transform(double magnification, bool x_reflection, Vec2d origin);

  void transform(double magnification, bool x_reflection, double rotation, Vec2d origin);

  EllipseParts get_parts();
  Vec2dArray query_parts(GeoPartType type, uint32_t id);

  uint32_t getLayer();
  void setLayer(uint32_t layer);

  qlib::Vec2d getRadius();
  void setRadius(qlib::Vec2d _radius);

  int getPointNum();
  void setPointNum(int num);

  Vec2d getCenterPoint();
  void setCenterPoint(Vec2d center);

  double getRotation();
  void setRotation(double rotation);

  // 渲染
  Vec2dArray render_aabb();
  Vec2dArray render_poly();
  Vec2dArray render_absorp();

  Polygon::s_ptr polygon;

  // 中心点
  Vec2d center;

  // 椭圆x半径和y半径
  Vec2d radius;

  mutable int point_num = 0;

  double tolerance;
  float rotation;

  uint32_t layer;
  uint32_t datatype;

  Vec2dArray box;
  Vec2dArray box_tran;

  PropertyArray properties;
  Repetition repetition;
};

}  // namespace qlib

#endif